package com.hifar.test.api.model;

import com.hifar.test.api.constant.EmployeeProcessingErrorCode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 增强版员工数据处理结果
 * 包含更详细的处理错误信息和统计
 */
public class EnhancedEmployeeProcessingResult {
    
    private String resultId;
    private boolean success;
    private List<DetailedErrorInfo> detailedErrors;
    private int totalCount;
    private int successCount;
    private int failureCount;
    private long processingTime;
    private String operation;
    private LocalDateTime startTime;
    private LocalDateTime endTime;
    private String requestId;
    private String clientIp;
    private String userId;
    private Map<String, Object> statistics;
    private List<String> warnings;
    private List<String> recommendations;
    
    public EnhancedEmployeeProcessingResult() {
        this.resultId = UUID.randomUUID().toString();
        this.success = true;
        this.detailedErrors = new ArrayList<>();
        this.totalCount = 0;
        this.successCount = 0;
        this.failureCount = 0;
        this.processingTime = 0;
        this.startTime = LocalDateTime.now();
        this.statistics = new HashMap<>();
        this.warnings = new ArrayList<>();
        this.recommendations = new ArrayList<>();
    }
    
    public EnhancedEmployeeProcessingResult(boolean success) {
        this();
        this.success = success;
    }
    
    /**
     * 添加详细错误信息
     */
    public void addDetailedError(EmployeeProcessingErrorCode errorCode, String operation, String dataId, Exception exception) {
        this.success = false;
        this.failureCount++;
        
        DetailedErrorInfo errorInfo = new DetailedErrorInfo();
        errorInfo.setErrorId(UUID.randomUUID().toString());
        errorInfo.setErrorCode(errorCode.getCode());
        errorInfo.setErrorMessage(errorCode.getMessage());
        errorInfo.setErrorSuggestion(errorCode.getSuggestion());
        errorInfo.setOperation(operation);
        errorInfo.setDataId(dataId);
        errorInfo.setRequestId(this.requestId);
        errorInfo.setClientIp(this.clientIp);
        errorInfo.setUserId(this.userId);
        
        // 设置错误分类和级别
        setErrorCategoryAndSeverity(errorInfo, errorCode);
        
        // 设置异常信息
        if (exception != null) {
            errorInfo.setStackTrace(getStackTrace(exception));
            errorInfo.setRootCause(extractRootCause(exception));
        }
        
        // 添加上下文信息
        addErrorContext(errorInfo, errorCode, operation, dataId);
        
        this.detailedErrors.add(errorInfo);
    }
    
    /**
     * 添加字段级错误
     */
    public void addFieldError(EmployeeProcessingErrorCode errorCode, String operation, String dataId, String fieldName, Object fieldValue, Exception exception) {
        DetailedErrorInfo errorInfo = new DetailedErrorInfo();
        errorInfo.setErrorId(UUID.randomUUID().toString());
        errorInfo.setErrorCode(errorCode.getCode());
        errorInfo.setErrorMessage(errorCode.getMessage());
        errorInfo.setErrorSuggestion(errorCode.getSuggestion());
        errorInfo.setOperation(operation);
        errorInfo.setDataId(dataId);
        errorInfo.setFieldName(fieldName);
        errorInfo.setFieldValue(fieldValue);
        errorInfo.setRequestId(this.requestId);
        errorInfo.setClientIp(this.clientIp);
        errorInfo.setUserId(this.userId);
        
        setErrorCategoryAndSeverity(errorInfo, errorCode);
        
        if (exception != null) {
            errorInfo.setStackTrace(getStackTrace(exception));
            errorInfo.setRootCause(extractRootCause(exception));
        }
        
        addErrorContext(errorInfo, errorCode, operation, dataId);
        
        this.detailedErrors.add(errorInfo);
        this.success = false;
        this.failureCount++;
    }
    
    /**
     * 标记处理成功
     */
    public void markSuccess() {
        this.successCount++;
    }
    
    /**
     * 添加警告信息
     */
    public void addWarning(String warning) {
        this.warnings.add(warning);
    }
    
    /**
     * 添加建议信息
     */
    public void addRecommendation(String recommendation) {
        this.recommendations.add(recommendation);
    }
    
    /**
     * 完成处理
     */
    public void complete() {
        this.endTime = LocalDateTime.now();
        if (this.startTime != null) {
            this.processingTime = java.time.Duration.between(this.startTime, this.endTime).toMillis();
        }
        this.success = this.failureCount == 0;
        updateStatistics();
    }
    
    /**
     * 设置总数
     */
    public void setTotalCount(int totalCount) {
        this.totalCount = totalCount;
    }
    
    /**
     * 设置处理时间
     */
    public void setProcessingTime(long processingTime) {
        this.processingTime = processingTime;
    }
    
    /**
     * 设置操作类型
     */
    public void setOperation(String operation) {
        this.operation = operation;
    }
    
    /**
     * 设置请求ID
     */
    public void setRequestId(String requestId) {
        this.requestId = requestId;
    }
    
    /**
     * 设置客户端IP
     */
    public void setClientIp(String clientIp) {
        this.clientIp = clientIp;
    }
    
    /**
     * 设置用户ID
     */
    public void setUserId(String userId) {
        this.userId = userId;
    }
    
    /**
     * 检查是否有错误
     */
    public boolean hasErrors() {
        return !detailedErrors.isEmpty();
    }
    
    /**
     * 获取错误数量
     */
    public int getErrorCount() {
        return detailedErrors.size();
    }
    
    /**
     * 获取处理成功率
     */
    public double getSuccessRate() {
        if (totalCount == 0) {
            return 0.0;
        }
        return (double) successCount / totalCount * 100;
    }
    
    /**
     * 获取平均处理时间
     */
    public double getAverageProcessingTime() {
        if (totalCount == 0) {
            return 0.0;
        }
        return (double) processingTime / totalCount;
    }
    
    /**
     * 获取错误统计
     */
    public Map<String, Integer> getErrorStatistics() {
        Map<String, Integer> stats = new HashMap<>();
        for (DetailedErrorInfo error : detailedErrors) {
            String category = error.getErrorCategory();
            stats.put(category, stats.getOrDefault(category, 0) + 1);
        }
        return stats;
    }
    
    /**
     * 设置错误分类和级别
     */
    private void setErrorCategoryAndSeverity(DetailedErrorInfo errorInfo, EmployeeProcessingErrorCode errorCode) {
        String code = errorCode.getCode();
        if (code.startsWith("PROC_001") || code.startsWith("PROC_002") || code.startsWith("PROC_003") || 
            code.startsWith("PROC_004") || code.startsWith("PROC_005") || code.startsWith("PROC_006")) {
            errorInfo.setErrorCategory("数据库操作");
            errorInfo.setErrorSeverity("HIGH");
        } else if (code.startsWith("PROC_007") || code.startsWith("PROC_008") || code.startsWith("PROC_009") || 
                   code.startsWith("PROC_010")) {
            errorInfo.setErrorCategory("数据转换");
            errorInfo.setErrorSeverity("MEDIUM");
        } else if (code.startsWith("PROC_011") || code.startsWith("PROC_012") || code.startsWith("PROC_013") || 
                   code.startsWith("PROC_014") || code.startsWith("PROC_015")) {
            errorInfo.setErrorCategory("业务逻辑");
            errorInfo.setErrorSeverity("MEDIUM");
        } else if (code.startsWith("PROC_016") || code.startsWith("PROC_017") || code.startsWith("PROC_018")) {
            errorInfo.setErrorCategory("权限控制");
            errorInfo.setErrorSeverity("HIGH");
        } else if (code.startsWith("PROC_019") || code.startsWith("PROC_020") || code.startsWith("PROC_021") || 
                   code.startsWith("PROC_022")) {
            errorInfo.setErrorCategory("系统错误");
            errorInfo.setErrorSeverity("CRITICAL");
        } else {
            errorInfo.setErrorCategory("其他");
            errorInfo.setErrorSeverity("LOW");
        }
    }
    
    /**
     * 添加错误上下文
     */
    private void addErrorContext(DetailedErrorInfo errorInfo, EmployeeProcessingErrorCode errorCode, String operation, String dataId) {
        errorInfo.addContext("errorCode", errorCode.getCode());
        errorInfo.addContext("operation", operation);
        errorInfo.addContext("dataId", dataId);
        errorInfo.addContext("timestamp", LocalDateTime.now().toString());
        errorInfo.addContext("requestId", this.requestId);
        errorInfo.addContext("clientIp", this.clientIp);
    }
    
    /**
     * 更新统计信息
     */
    private void updateStatistics() {
        this.statistics.put("totalCount", this.totalCount);
        this.statistics.put("successCount", this.successCount);
        this.statistics.put("failureCount", this.failureCount);
        this.statistics.put("successRate", getSuccessRate());
        this.statistics.put("processingTime", this.processingTime);
        this.statistics.put("averageProcessingTime", getAverageProcessingTime());
        this.statistics.put("errorCount", getErrorCount());
        this.statistics.put("warningCount", this.warnings.size());
        this.statistics.put("recommendationCount", this.recommendations.size());
        this.statistics.put("errorStatistics", getErrorStatistics());
    }
    
    /**
     * 获取异常堆栈信息
     */
    private String getStackTrace(Exception exception) {
        if (exception == null) {
            return null;
        }
        java.io.StringWriter sw = new java.io.StringWriter();
        java.io.PrintWriter pw = new java.io.PrintWriter(sw);
        exception.printStackTrace(pw);
        return sw.toString();
    }
    
    /**
     * 提取根本原因
     */
    private String extractRootCause(Exception exception) {
        if (exception == null) {
            return null;
        }
        
        Throwable cause = exception;
        while (cause.getCause() != null) {
            cause = cause.getCause();
        }
        
        return cause.getMessage() != null ? cause.getMessage() : cause.getClass().getSimpleName();
    }
    
    // Getters and Setters
    public String getResultId() {
        return resultId;
    }
    
    public void setResultId(String resultId) {
        this.resultId = resultId;
    }
    
    public boolean isSuccess() {
        return success;
    }
    
    public void setSuccess(boolean success) {
        this.success = success;
    }
    
    public List<DetailedErrorInfo> getDetailedErrors() {
        return detailedErrors;
    }
    
    public void setDetailedErrors(List<DetailedErrorInfo> detailedErrors) {
        this.detailedErrors = detailedErrors;
    }
    
    public int getTotalCount() {
        return totalCount;
    }
    
    public int getSuccessCount() {
        return successCount;
    }
    
    public void setSuccessCount(int successCount) {
        this.successCount = successCount;
    }
    
    public int getFailureCount() {
        return failureCount;
    }
    
    public void setFailureCount(int failureCount) {
        this.failureCount = failureCount;
    }
    
    public long getProcessingTime() {
        return processingTime;
    }
    
    public String getOperation() {
        return operation;
    }
    
    public LocalDateTime getStartTime() {
        return startTime;
    }
    
    public void setStartTime(LocalDateTime startTime) {
        this.startTime = startTime;
    }
    
    public LocalDateTime getEndTime() {
        return endTime;
    }
    
    public void setEndTime(LocalDateTime endTime) {
        this.endTime = endTime;
    }
    
    public String getRequestId() {
        return requestId;
    }
    
    public String getClientIp() {
        return clientIp;
    }
    
    public String getUserId() {
        return userId;
    }
    
    public Map<String, Object> getStatistics() {
        return statistics;
    }
    
    public void setStatistics(Map<String, Object> statistics) {
        this.statistics = statistics;
    }
    
    public List<String> getWarnings() {
        return warnings;
    }
    
    public void setWarnings(List<String> warnings) {
        this.warnings = warnings;
    }
    
    public List<String> getRecommendations() {
        return recommendations;
    }
    
    public void setRecommendations(List<String> recommendations) {
        this.recommendations = recommendations;
    }
    
    @Override
    public String toString() {
        return "EnhancedEmployeeProcessingResult{" +
                "resultId='" + resultId + '\'' +
                ", success=" + success +
                ", detailedErrors=" + detailedErrors.size() +
                ", totalCount=" + totalCount +
                ", successCount=" + successCount +
                ", failureCount=" + failureCount +
                ", processingTime=" + processingTime + "ms" +
                ", successRate=" + String.format("%.2f", getSuccessRate()) + "%" +
                ", averageTime=" + String.format("%.2f", getAverageProcessingTime()) + "ms" +
                '}';
    }
}
